package com.box.app.arithmetic

class Expression internal constructor(private val factors: List<Factor>) : Arithmetic, Argument, Iterable<Factor> {
    private val rpn = Rpn(factors)

    @Throws(ArithmeticError::class)
    fun call(variables: Map<String, Number>? = null) = rpn.call(variables)

    override fun toDescribe(isTight: Boolean, variables: Map<String, Number>?): String {
        return factors.joinToString("") { toDescribe(it, isTight, variables) }
    }

    override fun iterator() = factors.iterator()

    override fun toString() = toDescribe(true)
}

private fun toDescribe(factor: Factor, isTight: Boolean, variables: Map<String, Number>? = null): String {
    return when (factor) {
        is Variables -> factor.toDescribe(isTight, variables)
        is Symbol -> factor.toDescribe(isTight)
    }
}